package com.pine.dcts.handler;

import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.pine.dcts.common.BaseHandler;
import com.pine.dcts.common.DctsException;
import com.pine.dcts.common.Result;
import com.pine.dcts.config.DctsPropertis;
import com.pine.dcts.config.PluginManager;
import com.pine.dcts.entity.PluginInfo;
import com.pine.dcts.query.PluginInfoQuery;
import com.pine.dcts.service.PluginInfoService;
import com.pine.dcts.utils.UUIDUtils;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.io.FileUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.tomcat.util.http.fileupload.IOUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotNull;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.*;
import java.util.stream.Collector;
import java.util.stream.Collectors;

@RequestMapping("/plugin")
@RestController
@Slf4j
public class PluginInfoHandler extends BaseHandler {

    @Autowired
    private DctsPropertis dctsPropertis;
    @Autowired
    private PluginManager pluginManager;
    @Autowired
    private PluginInfoService pluginInfoService;
    @Autowired
    FileValidator fileValidator;


    @GetMapping("/page")
    public Result<Page<PluginInfo>> page(@Validated PluginInfoQuery query){
         return  Result.success(this.pluginInfoService.selectPage(query));
    }

    /**
     *  插件安装
     * @param multipartFile
     * @param pluginInfo
     */
    @PostMapping("/install")
    public Result installPlugin(@RequestParam("file") MultipartFile multipartFile, @Validated PluginInfo pluginInfo){
        if(!multipartFile.getOriginalFilename().endsWith(".zip")){
            throw new DctsException("插件包格式只能为zip");
        }
        //校验插件是否存在
        pluginManager.validateInstall(pluginInfo);
        FileOutputStream output = null;
        File file = new File(StringUtils.join(new
                String[]{dctsPropertis.getTemp(), UUIDUtils.getSimpleUUID()+".zip"}, File.separator) );
        try{
            if(file.exists()){
                file   = new File(StringUtils.join(new
                        String[]{dctsPropertis.getTemp(), UUIDUtils.getSimpleUUID()+".zip"}, File.separator) );
            }
            output =  new FileOutputStream(file);
            IOUtils.copy(multipartFile.getInputStream(),output);
            pluginManager.install(pluginInfo,file);
        }catch (DctsException e){
            log.error("插件安装错误",e);
            throw e;
        }catch (Exception e){
            log.error("插件安装错误",e);
            throw new DctsException("插件安装错误");
        }finally {
            org.apache.commons.io.IOUtils.closeQuietly(output);
            try {
                FileUtils.forceDelete(file);
            } catch (IOException ex) {
                log.warn("删除文件异常,文件名称：" + file.getAbsolutePath(), ex);
            }

        }
        return Result.success();

    }

    /**
     *  还原插件  还原上一个版本
     * @param id
     */
    @PostMapping("/reduction")
    public Result reduction(@NotNull(message = "插件id不能为空") Integer id){
        this.pluginManager.reduction(id);
        return Result.success();
    }

    /**
     *  停用
     * @param id
     */
    @PostMapping("/disabled")
    public Result disabled(@NotNull(message = "插件id不能为空") Integer id){
        this.pluginManager.disabled(id);
        return Result.success();
    }
    /**
     *  启用
     * @param id
     */
    @PostMapping("/enabled")
    public Result enabled(@NotNull(message = "插件id不能为空") Integer id){
        this.pluginManager.enabled(id);
        return Result.success();
    }


    /**
     * 卸载
     * @param id
     */

    @PostMapping("/unInstall")
    public Result unInstall(@NotNull(message = "插件id不能为空") Integer id){
        this.pluginManager.unInstall(id);
        return Result.success();
    }

    /**
     *  升级
     * @param id
     * @param multipartFile
     */
    @PostMapping("/upgrade")
    public Result upgrade(@NotNull(message = "插件id不能为空") Integer id, @NotBlank(message = "插件版本信息不能为空") String version, @RequestParam("file") MultipartFile multipartFile){
        if(!multipartFile.getOriginalFilename().endsWith(".zip")){
            throw new DctsException("插件包格式只能为zip");
        }
        FileOutputStream output = null;
        File file = new File(StringUtils.join(new
                String[]{dctsPropertis.getTemp(), UUIDUtils.getSimpleUUID()+".zip"}, File.separator) );
        try{
            if(file.exists()){
                file   = new File(StringUtils.join(new
                        String[]{dctsPropertis.getTemp(), UUIDUtils.getSimpleUUID()+".zip"}, File.separator) );
            }
            output =  new FileOutputStream(file);
            IOUtils.copy(multipartFile.getInputStream(),output);
            pluginManager.upgrade(id, version, file);
        }catch (DctsException e){
            log.error("插件升级错误",e);
            throw e;
        }catch (Exception e){
            log.error("插件升级错误",e);
            throw new DctsException("插件升级错误");
        }finally {
            org.apache.commons.io.IOUtils.closeQuietly(output);
            try {
                FileUtils.forceDelete(file);
            } catch (IOException ex) {
                log.warn("删除文件异常,文件名称：" + file.getAbsolutePath(), ex);
            }

        }
        return Result.success();
    }
    @GetMapping("/pluginList")
    public Result<List< Map<String,Object> >>  pluginList(){
        Map<String,List<PluginInfo>> map =   this.pluginInfoService.selectEnabledList()
                .stream().collect(Collectors.groupingBy(PluginInfo::getType));
      Set<String> keys =map.keySet();
      List< Map<String,Object> > result = new ArrayList<>();
      keys.forEach(key->{
          Map<String,Object> temp = new HashMap<>();
          temp.put("id",key);
          temp.put("name",key);
          temp.put("children",map.get(key));
          result.add(temp);
      });
       return Result.success(result);
    }
}
